package eduware.ctrl;

import java.util.Iterator;
import java.util.LinkedList;

/**************************************************************
 * class to handle all kinds of time dependant behaviours; it contains a number
 * of values associated with a certain time frame to get the according value for
 * a certain timeframe
 * 
 * @author Maik
 * 
 */
public class TimeDependantBehavior {
	/****************
	 * linked list containing all timeframes
	 */
	private LinkedList<TimeFrame> timeFrames = new LinkedList<TimeFrame>();

	/*********************
	 * consturctor to initialize the time dependant behaviour - the function
	 * requires a list of times and values such as the following:
	 * 
	 * <code>time: 6*60, 12*60, 18*60; values: 20,40,60,80; result: 00:00 - 06:00 = 20; 06:00-12:00 = 40; 12:00 - 18:00 = 60; 18:00 - 23:59 = 80</code>
	 * 
	 * @param times
	 *            array of integer values - number of minutes since 00:00
	 * @param deltaVal
	 *            time of associated data values
	 */
	public TimeDependantBehavior(int[] times, float[] deltaVal) {
		int i;
		// check whether the predefined format of the values matches
		if (times.length + 1 != deltaVal.length)
			throw new IllegalArgumentException("Bad parameter paid in use.");
		
		// iterate through the values and create the time frames
		int startTime = 0;
		for (i = 0; i < times.length; i++) {
			timeFrames.add(new TimeFrame(startTime, times[i], deltaVal[i]));
			startTime = times[i];
		}
		// generate the last time frame
		timeFrames
				.add(new TimeFrame(startTime, 24 * 60, deltaVal[times.length]));
	}

	/***********************************
	 * function to return the ratio associated with the current time
	 * @param time current time value
	 * @return delta ratio connected with current time
	 */
	public float getTimeRatio(int time) {
		Iterator<TimeFrame> ite = timeFrames.iterator();
		// iterate through all elements of the TDB
		while (ite.hasNext()) {
			TimeFrame tf = ite.next();
			if (tf.inTimeframe(time))
				return tf.getDeltaValue();
		}
		// otherwise return 1
		return 1.0f;
	}

	/**********************************
	 * function to return the ratio associated with the current time
	 * @param hours current hour
	 * @param minutes current minutes
	 * @return delta ratio connected with current time
	 */
	public float getTimeRatio(int hours, int minutes) {
		return this.getTimeRatio(hours * 60 + minutes);
	}

	/************************************
	 * data structure to handle the time frame internally
	 * @author Maik
	 *
	 */
	public class TimeFrame {
		
		/******************************
		 * beginning time of the frame
		 */
		private int beginTime;
		
		/******************************
		 * end time of the frame
		 */
		private int endTime;
		
		/******************************
		 * asscoiated delta value
		 */
		private float deltaValue;

		/******************************
		 * constructor to generate time frame
		 * @param beginTime beginning time of frame
		 * @param endTime end time of frame
		 * @param deltaValue associated delta value
		 */
		public TimeFrame(int beginTime, int endTime, float deltaValue) {
			this.beginTime = beginTime;
			this.endTime = endTime;
			this.deltaValue = deltaValue;
		}

		public int getBeginTime() {
			return beginTime;
		}

		public void setBeginTime(int beginTime) {
			this.beginTime = beginTime;
		}

		public int getEndTime() {
			return endTime;
		}

		public void setEndTime(int endTime) {
			this.endTime = endTime;
		}

		public float getDeltaValue() {
			return deltaValue;
		}

		public void setDeltaValue(float deltaValue) {
			this.deltaValue = deltaValue;
		}

		/***********************
		 * check whether timeframe matched a certain time
		 * @param time time value that should be checked
		 * @return boolean values whether time is inside the respective timeframe
		 */
		public boolean inTimeframe(int time) {
			if (time > this.beginTime && time <= this.endTime)
				return true;
			return false;
		}
	}

}
